/**
 *  学习目标：Todos 案例- Hooks版本
 *  1.✅ 拆分函数式组件
 *  2.✅ 列表数据定义和渲染
 *  3.✅ 根据id删除一条数据
 *  4.✅ 根据id更新选中状态和样式
 *  5.✅ 清除已完成
 *  6.✅ 统计剩余未完成的数量
 *  7.✅ 点谁谁高亮
 *  8.✅ 切换数据
 *  9.✅ 受控组件和新增数据
 *  10.✅ 小选影响全选
 *  11.✅全选影响小选
 *  12.✅ 数据缓存
 *
 *
 */
import React, { useEffect, useState } from 'react';
import './styles/base.css';
import './styles/index.css';

export default function App() {
  // 2.1 在App中定义state - list
  // 12.3 从localStorage中取出数据，作为useState的初始值
  const [list, setList] = useState(JSON.parse(localStorage.getItem('todo-list')) || []);

  // 7.1 在App中声明一个type状态
  const [type, setType] = useState(localStorage.getItem('todo-type'));

  // 12.1 使用useEffect监听list的变化，
  useEffect(() => {
    // 12.2 存入到localStorage中
    localStorage.setItem('todo-list', JSON.stringify(list));
  }, [list]);

  // 12.4 监听type- 存储type- 取出type作为useState的默认值
  useEffect(() => {
    localStorage.setItem('todo-type', type);
  }, [type]);

  // 3.3 App中定义删除的逻辑
  const handleDelById = (id) => {
    // 不能修改原数据
    // 复制数组
    const newList = [...list];
    const index = list.findIndex((item) => item.id === id);
    // 在新数组删除一条元素
    newList.splice(index, 1);
    // 更新list
    setList(newList);
  };

  // 4.1 App中定义操作list数据的方法，根据id修改对应isDone属性
  const handleUpdateById = (id) => {
    const newList = [...list];
    const index = list.findIndex((item) => item.id === id);
    newList[index].isDone = !newList[index].isDone;
    setList(newList);
  };

  // 5.3.  App中定义的handleClick， 并通过筛选完成清除的逻辑
  const handleClick = () => {
    // 筛选未完成的, 更新list
    const newList = list.filter((item) => !item.isDone);
    setList(newList);
  };

  // 6.1 定义一个restCount变量，通过统计list中isDome的数量的到
  // 💥list变化，或导致组件方法体内的代码重新执行。因此可以模拟计算属性
  const restCount = list.filter((item) => !item.isDone).length;

  const handleSelectBtn = (type) => {
    setType(type);
  };

  // 8.1 定义showList，根据type和list的值计算得来
  // 💥在App中定义showList
  const showList = list.filter((item) => {
    if (type === 'completed') return item.isDone;
    // 如果type 为active， 返回 item.isDone === false
    if (type === 'active') return !item.isDone;
    // 如果type 为completed，返回 item.isDone === true

    // 如果type 为all 返回 true
    return true;
  });

  // 8.2 把showList传给Main的list属性

  const handleAdd = (task) => {
    // 9.5 新增数据到list
    setList([
      {
        id: Date.now(),
        task,
        isDone: false,
      },
      ...list,
    ]);
  };

  const handleToggle = (checked) => {
    // 11.3 在App中定义选的处理函数， 处理全选逻辑
    console.log(checked, '我是全选触发时的checked');
    // 同步checked给所有的小选框
    setList(
      list.map((item) => ({
        ...item,
        isDone: checked,
      }))
    );
  };

  return (
    <section className="todoapp">
      {/* 头部 */}
      {/* 9.4 通过props传来的回调函数，handleAdd */}
      <Header handleAdd={handleAdd}></Header>
      {/* 主体 */}
      {/*  2.2 通过props传给Main */}
      {/* 3.2 父传子传递函数 */}
      {/* // 4.2. 父传子给Main组件传回调函数 handleUpdateById*/}
      {/* // 11.2 通过子传父，调用props传来的回调函数
       */}
      <Main
        list={showList}
        handleDelById={handleDelById}
        handleUpdateById={handleUpdateById}
        handleToggle={handleToggle}
      ></Main>
      {/* 底部 */}
      {/* 5.2.  父传子来的handleClick */}
      {/* 6.2 通过props传给Footer */}

      {/*   7.2 通过props传给Footer */}
      <Footer
        handleSelectBtn={handleSelectBtn}
        type={type}
        restCount={restCount}
        handleClick={handleClick}
      ></Footer>
    </section>
  );
}

function Header({ handleAdd }) {
  // 9.1 声明state来收集task
  const [task, setTask] = useState('');

  const handleKeyUp = (e) => {
    // 9.3 onKeyUp监听键盘事件，通过keyCode监听回车事件
    // 如果keyCode为13，代表回车事件，
    if (e.keyCode === 13) {
      // 9.7 非空判断，并提示用户不能为空
      if (!task.trim()) {
        alert('数据不能为空');
        return;
      }
      handleAdd(task);

      setTask('');
    }
    // 9.6 监听esc，清空数据
    if (e.keyCode === 27) {
      setTask('');
    }
  };

  return (
    <header className="header">
      <h1>todos</h1>
      <input
        className="new-todo"
        placeholder="需要做什么"
        autoFocus
        value={task}
        // 9.2 使用onChange改变state
        onChange={(e) => setTask(e.target.value)}
        onKeyUp={handleKeyUp}
      />
    </header>
  );
}
function Main({ list, handleDelById, handleUpdateById, handleToggle }) {
  // 10.1 定义一个isAll变量 - 计算属性
  // 💥 every在数组为空时，默认返回true
  const isAll = list.length ? list.every((item) => item.isDone) : false;
  // 10.2 将isAll绑定给全选的checked属性

  return (
    <section className="main">
      <input
        checked={isAll}
        id="toggle-all"
        className="toggle-all"
        type="checkbox"
        // 11.1 绑定onChange事件，获取到用户点击时的checked属性
        onChange={(e) => handleToggle(e.target.checked)}
      />
      <label htmlFor="toggle-all">全选</label>
      <ul className="todo-list">
        {/* 2.3 Main中遍历渲染 */}
        {list.map((item) => (
          // 4.4 处理选中的样式
          <li key={item.id} className={item.isDone ? 'completed' : ''}>
            <div className="view">
              <input
                className="toggle"
                type="checkbox"
                checked={item.isDone}
                // 4.3 给input的onChange事件绑定handleUpdateById，💥记得传id回去
                onChange={() => handleUpdateById(item.id)}
              />
              <label>{item.task}</label>
              {/* 3.1 给删除绑定onClick 事件对应的父传子回调函数 */}
              <button className="destroy" onClick={() => handleDelById(item.id)}></button>
            </div>
          </li>
        ))}
      </ul>
    </section>
  );
}

function Footer({ handleClick, restCount, type, handleSelectBtn }) {
  return (
    <footer className="footer">
      <span className="todo-count">
        {/* 6.3 在Footer中显示 */}
        <strong>{restCount}</strong> 剩余
      </span>
      <ul className="filters">
        <li>
          {/* 7.3 Footer中className使用排他判断- 多个className和一个type去比较  */}
          {/* 7.4 click事件， 绑定App中的处理函数，修改type的值 */}
          <a
            className={type === 'all' ? 'selected' : ''}
            href="#/"
            onClick={() => handleSelectBtn('all')}
          >
            全部
          </a>
        </li>
        <li>
          <a
            className={type === 'active' ? 'selected' : ''}
            href="#/active"
            onClick={() => handleSelectBtn('active')}
          >
            未完成
          </a>
        </li>
        <li>
          <a
            onClick={() => handleSelectBtn('completed')}
            className={type === 'completed' ? 'selected' : ''}
            href="#/completed"
          >
            已完成
          </a>
        </li>
      </ul>
      {/* 5.1. 给清除按钮绑定click事件， 父传子来的handleClick */}
      <button className="clear-completed" onClick={handleClick}>
        清除已完成
      </button>
    </footer>
  );
}
